package chapter_03;

// 数据类型、变量、数组

/*
1. Java是强类型语言

2. 简单数据类型
八个简单（或基本）的数据类型：
byte、short、int、long、char、float、double、boolean。这些类型可以分为4组：
· 整数：该组包括字节型（byte），短整型（short），整型（int），长整型（long），它们有符号整数。
· 浮点型数：该组包括浮点型（float），双精度型（double），它们代表有小数精度要求的数字。
· 字符：这个组包括字符型（char），它代表字符集的符号，例如字母和数字。
· 布尔型：这个组包括布尔型（boolean），它是一种特殊的类型，表示真/假值。

3. 整数类型
    A. 字节型
    有符号8位类型，数的范围是-128~127。
    通过byte关键来定义字节变量，例如：
    byte b, c;

    B. 短整型
    short是有符号的16位类型，数的范围是-32768~32767。因为它被定义为高字节有限（称为big-endian格式），使
    用short关键字声明变量。
    注意：“Endianness ”描述像short，int，和 long这些多字节数据类型是如何被存储在存储器中的。如果用2 个字
    节代表short，那么哪个字节在前，是高字节位（最重要的字节）还是低字节位（最不重要的字节）？说一台机器
    是big-endian，那意味着这个机器中最重要的字节在前，最不重要的字节在后。例如 SPARC 和PowerPC 的机器是
    big-endian ，而Intel x86 系列是 little-endian。

    C. 整型
    它是有符号的32位类型，数的范围是-2,147,483,648～2,147,483,647。
    任何时候你的整数表达式包含byte，short，int及字面量数字，在进行计算以前，所有表达式的类型被提升
    （promoted）到整型。
    整型是最通用并且有效的类型，当你想要计数用作或数组下标或进行整数计算时，你应该使用整型。似乎使用字节
    型和短整型可以节约空间，但是不能保证 Java 不会内部把那些类型提升到整型。记住，类型决定行为，而不是大
    小（惟一的例外是数组，字节型的数据保证每个数组元素只占用一个字节，短整型使用 2 个字节，整型将使用4
    个。）

    D. 长整型
    long是有符号的64位类型，它对于那些整型不足以保存所要求的数值时是有用的。长整型数的范围是相当大的。这
    使得大的、整个数字都被需要时，它是非常有用的。

4. 浮点型
浮点数字，也就是人们知道的实数，当计算的表达式有精度要求时被使用。
    A. 单精度浮点型（float）
    单精度浮点型（float）专指占用32位存储空间的单精度（single-precision）值。单精度在一些处理器上比双
    精度更快而且只占用双精度一半的空间，但是当值很大或很小的时候，它将变得不精确。当你需要小数部分并且
    对精度的要求不高时，单精度浮点型的变量是有用的。例如，当表示美元和分时，单精度浮点型是有用的。

    B. 双精度（double）浮点型
    双精度型，正如它的关键字“double”表示的，占用64位的存储空间。在一些现代的被优化用来进行高速数学计算
    的处理器上双精度型实际上比单精度的快。所有超出人类经验的数学函数，如sin( )，cos( )，和sqrt( )均返
    回双精度的值。当你需要保持多次反复迭代的计算的精确性时，或在操作值很大的数字时，双精度型是最好的选
    择。

5. 字符
在Java中，存储字符的数据类型是char。在C/C++中，char的宽是8位整数，但是Java不同，Java使用Unicode码代表字
符，所以它是16位的。
尽管char不是整数，但在许多情况中你可以对它们进行运算操作就好像它们是整数一样。这允许使用两个字符相加或者
对一个字符变量进行增量操作。

6. 布尔型
它的值只能是真（true）或假（false）这两个值中的一个。
使用boolean来声明：
boolean b;
b = false;

7. 进一步研究字面量
    7.1 整数字面量
    十进制
    八进制，0开头
    十六进制，0x或0X开头
    当一个字面量的值被赋给一个byte 或
    short型的变量时，如果字面量的值没有超过对应类型的范围时不会产生错误，所以，一个
    字面量总是可以被赋给一个long变量。但是，指定一个long字面量，你需要明白地告诉编译
    器字面量的值是long型，你可以通过在字面量的后面加一个大写或小写的L来做到这一点。

    7.2 浮点字面量
    浮点数代表带小数部分的十进制值。他们可通过标准记数法或科学记数法来表示。标
    准记数法（Standard notation）由整数部分加小数点加小数部分组成。例如2.0，3.14159，和
    0.6667 都是有效的标准记数法表示的浮点数字。科学记数法（Scientific notation）是浮点数
    加一表明乘以10的指定幂次的后缀，指数是紧跟E或 e 的一个十进制的数字，它可以是正
    值或是负值。例子如6.022E23，314159E-05，及2e+100。
    Java中的浮点字面量默认是双精度。为了指明一个浮点字面量，你必须在字面量后面
    加F或f。你也可以通过在字面量后面加D或d来指明一个浮点字面量，这样做当然是多余的。
    默认的双精度类型要占用64位存储空间，而精确低些的浮点类型仅仅需要32位。

    7.3 布尔型字面量
    true和false。

    7.4 字符字面量
    Java用Unicode字符集来表示字符。Java的字符是16位值，可以被转换为整数并可进行
    像加或减这样的整数运算。通过将字符包括在单引号之内来表示字符字面量。所有可见的
    ASCII字符都能直接被包括在单引号之内，例如'a'，'z'，and '@'。对于那些不能直接被包括
    的字符，有若干转义序列，这样允许你输入你需要的字符，例如'\'代表单个引号字符本身，
    '\n'代表换行符字符。为直接得到八进制或十六进制字符的值也有一个机制。对八进制来说，
    使用反斜线加3个阿拉伯数字。例如，'\141'是字母'a'。对十六进制来说，使用反斜线和u（\\u）
    加4个十六进制阿拉伯数字。例如，'\u0061'因为高位字节是零，代表ISO-Latin-1字符集中的
    'a'。'\ua432'是一个日文片假名字符。

    7.5 字符串字面量
    Java中的字符串字面量和其他大多数语言一样——将一系列字符用双引号括起来。字
    符串的例子如：
    "Hello World"
    "two\nlines"
    "\"This is in quotes\""
    为字符串定义的字符转义序列和八进制/十六进制记法在字符串内的工作方法一样。关
    于Java字符串应注意的一件重要的事情是它们必须在同一行开始和结束。不像其他语言有
    换行连接转义序列。

8. 变量
    A. 声明定义
    B. 变量的作用于和生存期
    变量在其作用域内被创建，离开其作用域时被撤消。
    尽管程序块能被嵌套，你不能将内部作用域声明的变量与其外部作用域声明的变量重名。在这一点上，Java不同于
    C和C++。

9. 类型转换与强制类型转换
    A. Java自动转换
    如果下列2个条件都能满足，那么将一种类型的数据赋给另外一种类型变量时，将执行自动类型转换：
    · 这2种类型是兼容的。
    · 目的类型数的范围比来源类型的大。

    B. 不兼容类型的强制转换
    通用格式为：
    (target-type) value
    其中，目标类型target-type指定了要将指定值转换成的类型。例如，下面的程序段将int型强制转换
    成byte型。如果整数的值超出了byte型的取值范围，它的值将会因为对byte型值域取模（整数除以
    byte得到的余数）而减少。
    int a;
    byte b;
    // ...
    b = (byte) a;

10. 表达式中类型的自动提升
byte b = 50;
b = b * 2; // Error
计算的时候b被提升为int类型，赋值的时候将int赋值给byte类型变量，编译器报错。解决如下：
byte b = 50;
b = (byte)(b * 2);
    A. 类型提升的约定
    所有的byte型和short型的值被提升到 int型。其次，如果一个操作数是long型，整个表达式将被
    提升到long型；如果一个操作数是float型，整个表达式将被提升到float型；如果有一个操作数是
    double型，计算结果就是double型。

11. 数组
Java数组的工作原理与C/C++不同。
    A. 一维数组
    先声明：
    type var-name[];
    再分配：
    var-name = new type[size];
    其中，type指定被分配的数据类型，size指定数组中变量的个数，var-name是被链接到数组的数组变量。
    将对数组的声明和对数组本身的分配结合起来也是可以的：
    type var-name[] = new type[size];
    数组可以在声明时被初始化。这个过程和简单类型初始化的过程一样。数组的初始化就是包括在花括号之内用逗号
    分开的表达式的列表。

    B. 多维数组
    多维数组实际上是数组的数组。
    int twoD[][] = new int[4][5];   // 4行5列
    当你给多维数组分配内存时，你只需指定第一个（最左边）维数的内存即可。你可以单独地给余下的维数分配内
    存。
    int twoD[][] = new int[4][];
    twoD[0] = new int[1];
    twoD[1] = new int[2];
    twoD[2] = new int[3];
    twoD[3] = new int[4];
    第二维分配的内存不一样。
    初始化多维数组是可能的。初始化多维数组只不过是把每一维的初始化列表用它自己的大括号括起来即可。

    C. 另一种数组声明语法
    声明数组还有第二种格式：
    type[] var-name;
    这里，方括号紧跟在类型标识符type的后面，而不是跟在数组变量名的后面。例如，
    下面的两个定义是等价的：
    int al[] = new int[3];
    int[] a2 = new int[3];
    下面的两个定义也是等价的：
    char twod1[][] = new char[3][4];
    char[][] twod2 = new char[3][4];

12. 字符串的简单介绍
Java不支持字符串基本类型，对于Java来说，字符串被定义为对象：
String str = "This is a test";

13. C/C++程序员请注意指针的用法
Java不支持或不允许指针。
Java不允许指针，是因为这样做将允许Javaapplet（小应用程序）突破Java运行环境和主机之间的防火墙（要知道，
指针能放在内存的任何地址，即使是Java运行系统之外的地址）。
 */

public class chapter_03 {

    public static void arr1() {
        //        int twoD[][] = new int[4][5];
        int twoD[][] = new int[4][];
        // 不规则数组需要分配内存到每一个元素
        twoD[0] = new int[5];
        twoD[1] = new int[5];
        twoD[2] = new int[5];
        twoD[3] = new int[5];

        int i, j, k = 0;
        for (i = 0; i < 4; i++)
            for (j = 0; j < 5; j++) {
                twoD[i][j] = k;
                k++;
            }

        for (i = 0; i < 4; i++) {
            for (j = 0; j < 5; j++)
                System.out.print(twoD[i][j] + " ");
            System.out.println();
        }
    }

    public static void arr2() {
        double m[][] = {
                { 0*0, 1*0, 2*0, 3*0 },
                { 0*1, 1*1, 2*1, 3*1 },
                { 0*2, 1*2, 2*2, 3*2 },
                { 0*3, 1*3, 2*3, 3*3 }
        };
        int i, j;
        for(i = 0; i < 4; i++) {
            for (j = 0; j < 4; j++)
                System.out.print(m[i][j] + " ");
            System.out.println();
        }
    }

    public static void main(String[] args) {
//        arr1();
        arr2();
    }
}
